#include "public.h"
#include <memory>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>

//********************************LString******************************************
void toUpper(char* str) noexcept
{
	if (nullptr == str || 0 == strlen(str))
		return;
	size_t len = strlen(str);
	for (size_t i = 0; i < len; ++i)
	{
		if (str[i] >= 'a' && str[i] <= 'z')
			str[i] -= 32;
	}
}


void toUpper(std::string& str) noexcept
{
	if (str.empty())
		return;
	size_t len = str.size();
	for (size_t i = 0; i < len; ++i)
	{
		if (str[i] >= 'a' && str[i] <= 'z')
			str[i] -= 32;
	}
}


void toLower(char* str) noexcept
{
	if (nullptr == str || 0 == strlen(str))
		return;
	size_t len = strlen(str);
	for (size_t i = 0; i < len; ++i)
	{
		if (str[i] >= 'A' && str[i] <= 'Z')
			str[i] += 32;
	}
}


void toLower(std::string& str) noexcept
{
	if (str.empty())
		return;
	size_t len = str.size();
	for (size_t i = 0; i < len; ++i)
	{
		if (str[i] >= 'A' && str[i] <= 'Z')
			str[i] += 32;
	}
}

bool deleteLChar(char* str, const char ch) noexcept
{
	if (NULL == str)
		return false;
	size_t i = 0;
	if ('\n' != ch)
	{
		while (i < strlen(str))
		{
			if (str[i] != ch)
				break;
			++i;
		}
	}
	else
	{
		while (i < strlen(str))
		{
			if ('\n' == str[i])
			{
				++i;
				continue;
			}
			if ('\r' == str[i] && '\n' == str[i + 1])
			{
				i += 2;
				continue;
			}
			break;
		}
	}
	if (0 == i)
		return true;
	for (size_t j = 0; i <= strlen(str); ++j,++i)
	{
		str[j] = str[i];
	}
	return true;
}

bool deleteRChar(char* str, const char ch) noexcept
{
	if (NULL == str)
		return false;
	int len = strlen(str);
	for (int i = len - 1; i >= 0; --i)
	{
		if (ch != str[i])
			break;
		str[i] = 0;
		if ('\n' == ch && i > 0 && '\r' == str[i - 1])
			--i;
		continue;
	}
	return true;
}

bool strTrim(char* strOut, const char* strIn) noexcept
{
	if (NULL == strOut || NULL == strIn)
		return false;
	int lenth = strlen(strIn);
	int begin = 0;
	int end = lenth - 1;
	for (; begin < lenth; ++begin)
	{
		if (strIn[begin] != ' ' && strIn[begin]!='\t')
			break;
	}

	for (; end >= begin; --end)
	{
		if ('\n' != strIn[end] && '\t' != strIn[end] && ' ' != strIn[end] && '\r' != strIn[end])
			break;
	}
	strncpy(strOut, strIn + begin, end - begin + 1);
	strOut[end - begin + 1] = 0;//由于strncpy没有碰到'\0'复制后结尾没有0，此处需要补0
	return true;
}

void strTrim(std::string& str) noexcept
{
	size_t lenth = str.size();
	if (0 == lenth)
		return;
	size_t begin = 0;
	size_t end = lenth-1;
	for (; begin < lenth; ++begin)
	{
		if (str[begin] != ' ' && str[begin] != '\t')
			break;
	}

	for (; end >= begin; --end)
	{
		if ('\n' != str[end] && '\t' != str[end] && ' ' != str[end] && '\r' != str[end])
			break;
	}
	std::string tmp(str, begin, end - begin + 1);
	str.swap(tmp);
	return;
}

void pathTrim(char* pathOut, const char* pathIn) noexcept
{
	strTrim(pathOut, pathIn);
	for (size_t i = 0; i < strlen(pathOut); ++i)
	{
		if (pathOut[i] == '\\')
			pathOut[i] = '/';
	}
}

std::shared_ptr<std::string> strReplace(char *str,const char *oldstr,const char *newstr)
{
	if(nullptr == str || 0 == strlen(str))
	{
		return nullptr;
	}
  if(nullptr == oldstr || nullptr == newstr)
		return nullptr;

	std::shared_ptr<std::string> dst = std::make_shared<std::string>();
	char *strStart = str;
	char *strPos = nullptr;
	for(;;)
	{
		strPos = strstr(strStart,oldstr);
		if(nullptr == strPos)
		{
			dst->append(strStart);
			return dst;
		}
		dst->append(strStart,strPos-strStart);
		dst->append(newstr);
		strStart = strPos+strlen(oldstr);
	}
}

bool isNum(char ch)
{
	if (ch >= '0' && ch <= '9')
		return true;
	return false;
}

bool isNum(const char* num)
{
	std::regex pattern("^[0-9]+$");

	return regex_match(num, pattern);
}


bool isInt(const char* integer)
{
	std::regex pattern("^[+-]?[0-9]+$");

	return regex_match(integer, pattern);
}

bool isInt32(const char* integer)
{
	std::regex pattern("^[+-]?(0+|0*[1-9][0-9]{0,9})$");
	if (!regex_match(integer, pattern))
		return false;
	int i = 0;
	int len = static_cast<int>(strlen(integer));
	if ('+' == integer[0] || '-' == integer[0])
		++i;
	while (i < len)
	{
		if ('0' != integer[i])
			break;
		++i;
	}
	if ((len - i) < 10)
		return true;
	if ('-' == integer[0] && (strcmp("2147483648", integer + i) >= 0))
		return true;
	if (strcmp("2147483647", integer + i) >= 0)
		return true;
	return false;
}

bool isUInt32(const char* integer)
{
	std::regex pattern("^[+]?(0+|0*[1-9][0-9]{0,9})$");
	if (!regex_match(integer, pattern))
		return false;
	int i = 0;
	int len = static_cast<int>(strlen(integer));
	if ('+' == integer[0])
		++i;
	while (i < len)
	{
		if ('0' != integer[i])
			break;
		++i;
	}
	if ((len - i) < 10)
		return true;
	if (strcmp("4294967295", integer + i) >= 0)
		return true;
	return false;
}

bool isInt64(const char* integer)
{
	std::regex pattern("^[+-]?(0+|0*[1-9][0-9]{0,18})$");
	if (!regex_match(integer, pattern))
		return false;
	int i = 0;
	int len = static_cast<int>(strlen(integer));
	if ('+' == integer[0] || '-' == integer[0])
		++i;
	while (i<len)
	{
		if ('0' != integer[i])
			break;
		++i;
	}
	if ((len - i) < 19)
		return true;
	if ('-' == integer[0] && (strcmp("9223372036854775808", integer + i) >= 0))
		return true;
	if (strcmp("9223372036854775807", integer + i) >= 0)
		return true;
	return false;

}

bool isUInt64(const char* integer)
{
	std::regex pattern("^[+]?(0+|0*[1-9][0-9]{0,19})$");
	if (!regex_match(integer, pattern))
		return false;
	int i = 0;
	int len = static_cast<int>(strlen(integer));
	if ('+' == integer[0])
		++i;
	while (i < len)
	{
		if ('0' != integer[i])
			break;
		++i;
	}
	if ((len - i) < 20)
		return true;
	if (strcmp("18446744073709551615", integer + i) >= 0)
		return true;
	return false;
}

//判定字符串是email
//函数内不做strTrim（）修剪
bool isMail(const char* email)
{
	// 定义邮箱格式的正则表达式模式
	std::regex pattern("^[a-zA-Z0-9]+([.-_][a-zA-Z0-9]+)*[-._]?@[a-zA-Z0-9]+([.-_][a-zA-Z0-9]+)*\\.[a-zA-Z]{2,}$");

	return regex_match(email, pattern);
}

//判定字符串是国内手机号码
//函数内不做strTrim（）修剪
bool isMobileNum(const char* number)
{
	std::regex pattern("^1([38][0-9]|4[5-9]|5[0-3,5-9]|66|7[0-8]|9[89])[0-9]{8}$");

	return regex_match(number, pattern);
}

//判定字符串是合法的账号：[a-zA-Z_0-9]组成且首位是字母，账号长度为6-18位
//函数内不做strTrim（）修剪
bool isAccount(const char* account)
{
	std::regex pattern("^[a-zA-Z]\\w{5,17}$");
	return regex_match(account, pattern);
}

bool isIPV4(const char* ipv4)
{
	std::regex pattern("([1-9][0-9]{0,2}\\.){3}[1-9][0-9]{0,2}");
	return regex_match(ipv4, pattern);
}

time_t strToTime(const char* stime)
{
	size_t slen = strlen(stime);
	char strtime[16]{ 0 };
	size_t strlen = 0;
	//先取出字符串中的所有数字到strtime，如果输入正确strtime应为yyyymmddhh24miss格式长度为14
	for (size_t i = 0; i < slen&&strlen<15; ++i)
	{
		if (isNum(stime[i]))
		{
			strtime[strlen] = stime[i];
			++strlen;
		}
	}
	if (14 != strlen)
		return -1;
	struct tm tm;
	char yyyy[5]{ 0 };
	char buf[3]{ 0 };
	strncpy(yyyy, strtime, 4);
	if (0 > (tm.tm_year = atoi(yyyy) - 1900))
		return -1;

	strncpy(buf, strtime + 4, 2);
	if (11 < (tm.tm_mon = atoi(buf) - 1))
		return -1;

	strncpy(buf, strtime + 6, 2);
	if (31 < (tm.tm_mday = atoi(buf)))
		return -1;

	strncpy(buf, strtime + 8, 2);
	if (23 < (tm.tm_hour = atoi(buf)))
		return -1;

	strncpy(buf, strtime + 10, 2);
	if (59 < (tm.tm_min = atoi(buf)))
		return -1;

	strncpy(buf, strtime + 12, 2);
	if (59 < (tm.tm_sec = atoi(buf)))
		return -1;
	
	return mktime(&tm);
}


//--------------------class SPlitstrs-------------------------

SplitStrs::SplitStrs():
	vString_(),
	isClear_(true)
{

}

SplitStrs::SplitStrs(const std::string& src, const char* delimiter, const bool trim):
	vString_(),
	isClear_(true)
{
	this->split(src, delimiter, trim);
}
SplitStrs::~SplitStrs()
{

}

size_t SplitStrs::split(const std::string& src, const char* delimiter, const bool trim)
{
	if (!isClear_)
	{
		vString_.clear();
		isClear_ = true;
	}
	std::string::size_type begin = 0;
	std::string::size_type end = 0;

	while (std::string::npos != (end =src.find(delimiter,begin)))
	{
		vString_.emplace_back(src, begin, end - begin);
		if (trim)
			strTrim(vString_.back());
		begin = end + static_cast<std::string::size_type>(strlen(delimiter));
	}
	isClear_ = false;
	return vString_.size();
}

size_t SplitStrs::count() noexcept
{
	return vString_.size();
}

bool SplitStrs::getValue(const size_t index, char* value, const size_t len)
{
	if (NULL == value || (0!=len && len <= vString_[index].size()) || index >= vString_.size())
		return false;
	if (0 == len)
	{
		strcpy(value, vString_[index].c_str());
	}
	else
	{
		strncpy(value, vString_[index].c_str(), len);
	}
	return true;
}

bool SplitStrs::getValue(const size_t index, std::string& value)
{
	if (isClear_ || index >= vString_.size())
		return false;
	value = vString_[index];
	return true;
}

bool SplitStrs::getValue(const size_t index, int32_t& value)
{
	if (isClear_ || index >= vString_.size())
		return false;
	if (!isInt32(vString_[index].c_str()))
		return false;
	value = static_cast<int32_t>(atoi(vString_[index].c_str()));
	return true;
}

bool SplitStrs::getValue(const size_t index, uint32_t& value)
{
	if (isClear_ || index >= vString_.size())
		return false;
	if (!isUInt32(vString_[index].c_str()))
		return false;
	value = static_cast<uint32_t>(atoll(vString_[index].c_str()));
	return true;
}

bool SplitStrs::getValue(const size_t index, int64_t& value)
{
	if (isClear_ || index >= vString_.size())
		return false;
	if (!isInt64(vString_[index].c_str()))
		return false;
	value = static_cast<int64_t>(atoll(vString_[index].c_str()));
	return true;
}

bool SplitStrs::getValue(const size_t index, uint64_t& value)
{
	if (isClear_ || index >= vString_.size())
		return false;
	if (!isUInt64(vString_[index].c_str()))
		return false;
	value = static_cast<uint64_t>(strtoull(vString_[index].c_str(),nullptr,10));
	return true;
}

bool SplitStrs::getValue(const size_t index, double& value)
{
	if (isClear_ || index>=vString_.size())
		return false;
	value = atof(vString_[index].c_str());
	return true;
}

bool SplitStrs::getValue(const size_t index, bool& value)
{
	if (isClear_ || index >= vString_.size())
		return false;
	std::string tmp(vString_[index]);
	toLower(tmp);
	if (0 == tmp.compare("true") || 0 == tmp.compare("1"))
	{
		value = true;
		return true;
	}
	else if(0 == tmp.compare("false") || 0 == tmp.compare("0"))
	{
		value = false;
		return true;
	}

	return false;
}


bool getXMLValue(const char* xml, const char* tag, char* value, size_t size)
{
	if (nullptr == value || nullptr == tag || nullptr == xml)
		return false;
	char* start(nullptr), * end(nullptr);
	char startTag[64]{ 0 }, endTag[64]{ 0 };
	size_t taglen = strlen(tag);
	snprintf(startTag, 63, "<%s>", tag);
	snprintf(endTag, 63, "</%s>", tag);
	start = (char*)strstr(xml, startTag);
	if (nullptr != start)
	{
		start = start + taglen + 2;
		end = (char*)strstr(start, endTag);
	}
	if (nullptr == start || nullptr == end)
		return false;

	char* tmp = (char*)malloc((size+4)*sizeof(char));
	if (nullptr == tmp)
		return false;
	memset(tmp, 0, (size + 4) * sizeof(char));
	if ((end - start) >= size)
		return false;
	strncpy(tmp, start, end - start);
	strTrim(value, tmp);
	free(tmp);
	return true;
}

bool getXMLValue(const std::string& xml,const std::string& tag, std::string& value)
{
	std::string startTag, endTag;
	startTag = "<" + tag + ">";
	endTag = "</" + tag + ">";
	size_t start(std::string::npos);
	size_t end(std::string::npos);
	if (std::string::npos!= (start = xml.find(startTag)))
	{
		end = xml.find(endTag, start);
	}
	if (std::string::npos == start || std::string::npos == end)
		return false;
	start = start + tag.size() + 2;
	value = xml.substr(start, end-start);
	return true;
}
//获取xml字符串中的tag标签的值（bool）
bool getXMLValue(const char* xml, const char* tag, bool* value)
{
	char buf[16];
	if (!getXMLValue(xml, tag, buf, 16))
		return false;
	toLower(buf);
	if (0 == strcmp(buf, "true") || 0 == strcmp(buf, "1"))
	{
		*value = true;
		return true;
	}
	if (0 == strcmp(buf, "false") || 0 == strcmp(buf, "0"))
	{
		*value = false;
		return true;
	}
	return false;
}
//获取xml字符串中的tag标签的值（int32_t）范围：-2147483648~2147483647
bool getXMLValue(const char* xml, const char* tag, int32_t* value)
{
	char buf[12];
	if (!getXMLValue(xml, tag, buf, 12))
		return false;
	*value = atoi(buf);
	return true;
}
//获取xml字符串中的tag标签的值（uint32_t）范围：0~4294967295
bool getXMLValue(const char* xml, const char* tag, uint32_t* value)
{
	char buf[12];
	if (!getXMLValue(xml, tag, buf, 12))
		return false;
	*value = static_cast<uint32_t>(atoll(buf));
	return true;
}
//获取xml字符串中的tag标签的值（double）
bool getXMLValue(const char* xml, const char* tag, double* value)
{
	char buf[24];
	if (!getXMLValue(xml, tag, buf, 24))
		return false;
	*value = strtod(buf,nullptr);
	return true;
}
//获取xml字符串中的tag标签的值（int64_t）范围：-9223372036854775808~9223372036854775807
bool getXMLValue(const char* xml, const char* tag, int64_t* value)
{
	char buf[24];
	if (!getXMLValue(xml, tag, buf, 24))
		return false;
	*value = atoll(buf);
	return true;
}

//***************************************LTime&LTimer******************************************

LTime::LTime()
	:tm_(new tm)
	,isCurrentTime_(true)
{
	getCurrentTime();
}

LTime::LTime(const time_t* time)
	:tm_(new tm)
	,isCurrentTime_(false)
{
	SLocaltime(time, tm_);
}

LTime::~LTime()
{
	delete tm_;
}

void LTime::setTimeNow()
{
	isCurrentTime_ = true;
	getCurrentTime();
}

void LTime::setTime(const time_t* time)
{
	SLocaltime(time,tm_);
	isCurrentTime_ = false;
}

std::string LTime::getDate(const char* fmt)
{
	char buf[32] = { 0 };
	if (isCurrentTime_)
	{
		getCurrentTime();
	}

	if (nullptr == fmt || 0 == strcmp(fmt, "yyyy-mm-dd hh24:mi:ss"))
	{
		snprintf(buf,20, "%04d-%02d-%02d %02d:%02d:%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday, tm_->tm_hour, tm_->tm_min, tm_->tm_sec);
	}
	else if (0 == strcmp(fmt, "yyyy-mm-dd hh24:mi"))
	{
		snprintf(buf, 17, "%04d-%02d-%02d %02d:%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday, tm_->tm_hour, tm_->tm_min);
	}
	else if (0 == strcmp(fmt, "yyyy-mm-dd hh24"))
	{
		snprintf(buf, 14, "%04d-%02d-%02d %02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday, tm_->tm_hour);
	}
	else if (0 == strcmp(fmt, "yyyy-mm-dd"))
	{
		snprintf(buf, 11, "%04d-%02d-%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday);
	}
	else if (0 == strcmp(fmt, "yyyy-mm"))
	{
		snprintf(buf, 8, "%04d-%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1);
	}
	else if (0 == strcmp(fmt, "yyyymmddhh24miss"))
	{
		snprintf(buf, 15, "%04d%02d%02d%02d%02d%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday, tm_->tm_hour, tm_->tm_min, tm_->tm_sec);
	}
	else if (0 == strcmp(fmt, "yyyymmddhh24mi"))
	{
		snprintf(buf, 13, "%04d%02d%02d%02d%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday, tm_->tm_hour, tm_->tm_min);
	}
	else if (0 == strcmp(fmt, "yyyymmddhh24"))
	{
		snprintf(buf, 11, "%04d%02d%02d%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday, tm_->tm_hour);
	}
	else if (0 == strcmp(fmt, "yyyymmdd"))
	{
		snprintf(buf, 9, "%04d%02d%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday);
	}
	else if (0 == strcmp(fmt, "hh24miss"))
	{
		snprintf(buf, 7, "%02d%02d%02d"
			, tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday);
	}
	return buf;
}
std::string LTime::getYear()
{
	return std::to_string(tm_->tm_year + 1900);
}
std::string LTime::getMonth()
{
	char buf[4]{ 0 };
	snprintf(buf, 3, "%02d", tm_->tm_mon + 1);
	return buf;
}
std::string LTime::getDay()
{
	char buf[4]{ 0 };
	snprintf(buf, 3, "%02d", tm_->tm_mday);
	return buf;
}

std::string LTime::getHour()
{
	char buf[4]{ 0 };
	snprintf(buf, 3, "%02d", tm_->tm_hour);
	return buf;
}

std::string LTime::getMinute()
{
	char buf[4]{ 0 };
	snprintf(buf, 3, "%02d", tm_->tm_min);
	return buf;
}

std::string LTime::getSeconds()
{
	char buf[4]{ 0 };
	snprintf(buf, 3, "%02d", tm_->tm_sec);
	return buf;
}

void LTime::getCurrentTime()
{
	time_t t;
	time(&t);
	SLocaltime(&t,tm_);
}

LTimer::LTimer()
	:startTime_(std::chrono::high_resolution_clock::now())
	,endTime_()
{}

void LTimer::start()
{
	startTime_ = std::chrono::high_resolution_clock::now();
}

double LTimer::getElapsed()
{
	endTime_ = std::chrono::high_resolution_clock::now();
	std::chrono::duration<double> du = endTime_ - startTime_;
	start();
	return du.count();
}

//************************************LFunction**********************************************

bool createDir(const char* path, bool isFileName)
{
	int len = strlen(path);
	if (len >= MAX_DIR_LENGTH)
		return false;
	char tmppath[MAX_DIR_LENGTH];
	char dir[MAX_DIR_LENGTH] = { 0 };
	pathTrim(tmppath, path);
	len = strlen(tmppath);
	for (int i = 1; i < len; ++i)
	{
		if (path[i] != '/')
			continue;
		strncpy(dir, tmppath, i);
		dir[i] = 0;
		if (0 == access(dir, 0))
			continue;
		if (0 != MKDIR(dir))
			return false;
	}
	if (!isFileName)
	{
		if (0 != access(dir, 0))
		{
			if (0 != MKDIR(dir))
				return false;
		}
	}
	return true;
}

FILE* FOPEN(const char* filename, const char* mode)
{
	if ('w' == mode[0] || 'a' == mode[0])
	{
		if (!createDir(filename, true))
			return nullptr;
	}
	return fopen(filename, mode);

}

size_t fileSize(const char* filename)
{
	struct stat st;
	if (stat(filename, &st) < 0)
		return -1;
	return st.st_size;
}

bool fileMTime(const char* filename, std::string& mtime, const char* fmt)
{
	struct stat st;
	if (stat(filename, &st) < 0)
		return false;
	LTime tm(&st.st_mtime);
	mtime = tm.getDate(fmt);
	if (0 == mtime.size())
		return false;
	return true;
}


bool REMOVE(const char* filename, const int times)
{
	if (access(filename, 0) != 0)
		return false;
	for (int i = 0; i < times; ++i)
	{
		if (0 == remove(filename))
			return true;
		SLEEP(100);
	}
	return false;
}

bool RENAME(const char* oldpath, const char* newpath, bool isFileName, const int times)
{
	if (0 != access(oldpath, 0))
		return false;
	if (!createDir(newpath, isFileName))
		return false;
	for (int i = 0; i < times; ++i)
	{
		if (0 == rename(oldpath, newpath))
			return true;
		SLEEP(100);
	}
	return false;
}

//**********************************************Logger**************************************

Logger::Logger()
	: filename_("")
	, openmode_("")
	, logfile_(nullptr)
	, cache_(false)
	, backup_(true)
	, debug_(false)
	, maxLogFileSize_(10)
	, spin_()
{}

Logger::~Logger()
{
	close();
}

Logger& Logger::getInstance()
{
	static Logger log;
	return log;
}

void Logger::close()
{
	if (nullptr != logfile_)
	{
		fclose(logfile_);
		logfile_ = nullptr;
		filename_.clear();
		memset(openmode_, 0, 11);
		backup_ = true;
		cache_ = false;
		
	}
}

bool Logger::open(std::string filename, const char* openmode, bool backup, bool cache,size_t maxLogFileSize)
{
	this->close();
	if (!createDir(filename.c_str(), true))
		return false;
	filename_ = filename;
	strcpy(openmode_, openmode);
	backup_ = backup;
	cache_ = cache;
	if (10 < maxLogFileSize)
	{
		maxLogFileSize_ = maxLogFileSize;
	}
	else
	{
		maxLogFileSize_ = 10;
	}
	if (nullptr == (logfile_ = FOPEN(filename_.c_str(), openmode_)))
		return false;
	return true;
}

void Logger::setMaxLogFileSize(size_t size)
{
	if (size >= 10)
	{
		maxLogFileSize_ = size;
	}
	else
	{
		maxLogFileSize_ = 10;
	}
}

bool Logger::backupLogFile(LTime& time)
{
	if (nullptr == logfile_ || !backup_)
		return false;
	if (maxLogFileSize_ * 1024 * 1024 <= static_cast<size_t>(ftell(logfile_)))
	{
		std::string bakFilename = filename_ + "." + time.getDate("yyyymmddhh24miss");
		fclose(logfile_);
		logfile_ = nullptr;
		if (!RENAME(filename_.c_str(), bakFilename.c_str()))
			return false;
		if (nullptr == (logfile_ = FOPEN(filename_.c_str(), openmode_)))
			return false;
	}
	return true;
}

bool Logger::info(const char* fmt, ...)
{
	if (nullptr == logfile_)
		return false;

	std::lock_guard<SpinLock> my_lock(spin_);
	LTime time;
	if (!backupLogFile(time))
		return false;
	fprintf(logfile_, "%s %s ", time.getDate("yyyymmddhh24miss").c_str(), "[info]");
	va_list ap;
	va_start(ap, fmt);
	vfprintf(logfile_, fmt, ap);
	va_end(ap);
	return true;
}
bool Logger::error(const char* fmt, ...)
{
	if (nullptr == logfile_)
		return false;

	std::lock_guard<SpinLock> my_lock(spin_);
	LTime time;
	if (!backupLogFile(time))
		return false;
	fprintf(logfile_, "%s %s ", time.getDate("yyyymmddhh24miss").c_str(), "[error]");
	va_list ap;
	va_start(ap, fmt);
	vfprintf(logfile_, fmt, ap);
	va_end(ap);
	return true;
}
bool Logger::fatal(const char* fmt, ...)
{
	if (nullptr == logfile_)
		return false;

	std::lock_guard<SpinLock> my_lock(spin_);
	LTime time;
	if (!backupLogFile(time))
		return false;
	fprintf(logfile_, "%s %s ", time.getDate("yyyymmddhh24miss").c_str(), "[fatal]");
	va_list ap;
	va_start(ap, fmt);
	vfprintf(logfile_, fmt, ap);
	va_end(ap);
	return true;
}
bool Logger::debug(const char* fmt, ...)
{
	if (debug_)
	{
		if (nullptr == logfile_)
			return false;

		std::lock_guard<SpinLock> my_lock(spin_);
		LTime time;
		if (!backupLogFile(time))
			return false;
		fprintf(logfile_, "%s %s ", time.getDate("yyyymmddhh24miss").c_str(), "[debug]");
		va_list ap;
		va_start(ap, fmt);
		vfprintf(logfile_, fmt, ap);
		va_end(ap);
	}
	return true;
}

bool Logger::log(const char* fmt, ...)
{
	if (nullptr == logfile_)
		return false;

	std::lock_guard<SpinLock> my_lock(spin_);
	LTime time;
	if (!backupLogFile(time))
		return false;
	va_list ap;
	va_start(ap, fmt);
	vfprintf(logfile_, fmt, ap);
	va_end(ap);
	return true;
}



//*********************************************LFile***********************************************

LFile::LFile():
	isOpened_(false),
	fp_(NULL),
	cache_(false),
	path_{ 0 }
{}

/*
	path:需要打开的文件的全路径
	mode：文件的打开模式，与fopen的打开模式相同
*/
LFile::LFile(const char* path, const char* mode, bool cache):
	isOpened_(false),
	fp_(NULL),
	cache_(true),
	path_{ 0 }
{
	this->open(path, mode ,cache);
}

LFile::~LFile()
{
	this->clear();
}


bool LFile::isOpened()
{
	return isOpened_;
}

bool LFile::isEnd()
{
	if (!isOpened_)
		return false;
	return feof(fp_);
}

void LFile::clear()
{
	if (!isOpened_)
		return;
	fclose(fp_);
	fp_ = NULL;
	isOpened_ = false;
	cache_ = false;
	memset(path_, 0, MAX_FILENAME_LENGTH);
	return;
}

void LFile::flush()
{
	fflush(fp_);
}

bool LFile::open(const char* path, const char* mode, bool cache)
{
	clear();
	int length = strlen(path);
	if (length >= MAX_FILENAME_LENGTH)//本操作类不处理超过MAX_FILENAME_LENGTH个字符的路径
		return false;
	pathTrim(path_, path);
	if ((fp_ = fopen(path_, mode)) == NULL)
	{
		memset(path_, 0, MAX_FILENAME_LENGTH);
		return false;
	}
	isOpened_ = true;
	cache_ = cache;
	return true;

}

int LFile::seek(long offset, int origin)
{
	if (!isOpened_)
		return -1;
	return fseek(fp_, offset, origin);
}

int LFile::tell()
{
	if (!isOpened_)
		return -1;
	return ftell(fp_);
}


//获取已打开的文件全名，含扩展名,提取到buf中
//bufsize:buf的长度
bool LFile::getFullName(char* buf, int bufsize)
{
	if (!isOpened_)
		return false;
	return this->getFileName(buf, bufsize, path_);
}
bool LFile::getFullName(char* buf, int bufsize, const char* path)	//获取文件全名，含扩展名
{
	int length = strlen(path);
	if (0 == length)
		return false;
	memset(buf, 0, bufsize);
	for (int i = length - 1; i >= 0; --i)
	{
		if (path[i] == '/' || path[i] == '\\')
		{
			if ((length -1 - i) >= bufsize)
				return false;
			strcpy(buf, path+i+1);
			return true;
		}
	}
	if (length >= bufsize)
		return false;
	strcpy(buf, path);
	return true;
}


// 获取已打开的文件名，不含扩展名,提取到buf中
// buf在函数中会清零
// bufsize:buf的长度
bool LFile::getFileName(char* buf, int bufsize)
{
	if (!isOpened_)
		return false;
	return getFileName(buf, bufsize, path_);
}
bool LFile::getFileName(char* buf, int bufsize, const char* path)//获取文件名，不含扩展名
{
	int length = strlen(path);
	if (0 == length)
		return false;
	int i, j;
	for (j = length - 1; j >= 0; --j)
	{
		if (path[j] == '.')
			break;
	}
	memset(buf, 0, bufsize);
	for (i = j - 1; i >= 0; --i)
	{
		if (path[i] == '/' || path[i] == '\\')
		{
			if (j - i > bufsize || j - i == 1)
				return false;
			strncpy(buf, path + i + 1, j - i - 1);
			return true;
		}
	}
	if (j < 1)
		return false;
	strncpy(buf, path, j);
	return true;
}


// 获取已打开的文件的扩展名,提取到buf中
// buf在函数中会清零
// bufsize:buf的长度
bool LFile::getExt(char* buf, int bufsize)
{
	if (!isOpened_)
		return false;
	return getExt(buf, bufsize, path_);
}
// 静态方法，获得扩展名,提取到buf中
// buf在函数中会清零
// bufsize:buf的长度
bool LFile::getExt(char* buf, int bufsize, const char* path)//获得扩展名
{
	int length = strlen(path);
	if (0 == length)
		return false;
	int i = length - 1;
	memset(buf, 0, bufsize);
	for (; i >= 0; --i)
	{
		if ('.' == path[i])
		{
			if (length - i > bufsize)
				return false;
			strcpy(buf, path + i+1);
			return true;
		}
	}
	return false;
}

bool LFile::getStrs(char* buf, int bufsize, int star, int size)
{
	if (!isOpened_)
		return false;
	return getStrs(buf, bufsize,star,size, fp_);
}
//获取文本中当前位置第star（第一个字符star为0而不是1）个字符开始的size个字符的字符串，
//文本指针指到取到的最后一个字符后面,获取的字符串存到buf中
bool LFile::getStrs(char* buf, int bufsize, int star, int size, FILE* fp)
{
	if (bufsize<=size || fp==NULL)
	{
		return false;
	}
	fseek(fp, star, SEEK_CUR);
	memset(buf, 0, bufsize);
	fread(buf, 1, size, fp);
	return true;//成功返回1
}

//函数把指针指向下一行开头
FResult LFile::toNextLine(FILE* fp)
{
	if (NULL == fp)
		return FResult::error;						//出错返回error(-1)
	char* buf = new char[512];
	while (1)
	{
		fgets(buf, 512, fp);
		if (feof(fp))
		{
			delete[]buf;
			return FResult::eof;					//文件结束返回eof(2)
		}
		fseek(fp, -1, SEEK_CUR);
		fgets(buf, 2, fp);
		if (buf[0] == '\n')
		{
			delete[] buf;
			return FResult::success;					//成功返回success(1)
		}
	}
}

bool LFile::closeAndRemove()
{
	if (!isOpened_)
		return false;
	fclose(fp_);
	fp_ = NULL;
	isOpened_ = false;
	cache_ = true;
	int ret = remove(path_);
	memset(path_, 0, MAX_FILENAME_LENGTH);
	if (0 == ret)
		return true;
	return false;
}

int LFile::puts(const char* buf)
{
	if (!isOpened_)
		return -1;
	int ret = fputs(buf, fp_);
	if (!cache_)
		fflush(fp_);
	return ret;
}

size_t LFile::write(const void* ptr, size_t size, size_t nmemb)
{
	if (!isOpened_)
		return 0;
	size_t n = fwrite(ptr, size, nmemb, fp_);
	if (!cache_)
		fflush(fp_);
	return n;
}

int LFile::fprintf(const char* fmt, ...)
{
	if (NULL == fp_)
		return -1;
	va_list arg;
	va_start(arg, fmt);
	int ret = vfprintf(fp_, fmt, arg);
	va_end(arg);
	if (!cache_)
		fflush(fp_);
	return ret;

}

int LFile::getc()
{
	if (!isOpened_)
		return EOF;
	return fgetc(fp_);
}

size_t LFile::read(void* ptr,size_t nmemb,size_t size)
{
	if (!isOpened_)
		return EOF;
	return fread(ptr, size, nmemb, fp_);
}

FResult LFile::getDelim(FILE* fp, char* buf, int bufsize, char delimiter,bool igndelim)
{
	int i = 0;
	char ch;
	memset(buf, 0, bufsize);
	for(;i<bufsize-1;++i)
	{
		ch = fgetc(fp);
		if (EOF == ch)
		{
			return FResult::eof;
		}
		buf[i] = ch;
		if (delimiter != ch)
			continue;

		if (igndelim == true)
		{
			buf[i] = 0;
			if ('\n' == delimiter && buf[i - 1] == '\r')
				buf[i - 1] = 0;
		}

		return FResult::success;

	}
	return FResult::nodelim;

}

FResult LFile::getDelim(char* buf, int bufsize, char delimiter, bool igndelim)
{
	if (!isOpened_)
		return FResult::error;
	return getDelim(fp_, buf, bufsize, delimiter, igndelim);
}

FResult LFile::getU8Char(std::string& uchar)
{
	if (!isOpened_)
		return FResult::error;
	char ch = fgetc(fp_);
	if (feof(fp_))
		return FResult::eof;
	uchar.clear();
	uchar.push_back(ch);
	int len = 1;
	if ((ch & 0xe0) == 0xc0)
		len = 2;
	if ((ch & 0xf0) == 0xe0)
		len = 3;
	if ((ch & 0xf8) == 0xf0)
		len = 4;
	--len;
	for (; len > 0; --len)
	{
		ch = fgetc(fp_);
		if (feof(fp_))
			break;
		uchar.push_back(ch);
	}
	return FResult::success;

}


FResult LFile::getGbkChar(std::string& uchar)
{
	if (!isOpened_)
		return FResult::error;
	char ch = fgetc(fp_);
	if (feof(fp_))
		return FResult::eof;
	uchar.clear();
	uchar.push_back(ch);
	if ((ch & 0x80) == 0x80)
	{
		if (EOF != (ch = fgetc(fp_)))
		{
			uchar.push_back(ch);
		}
	}
	return FResult::success;
}

bool loadConfigFile(std::map<std::string, std::string>& config, const std::string filename)
{
	std::ifstream file(filename);
	std::string line;
	std::string key;
	std::string value;
	if (!file.is_open())
		return false;

	while (getline(file, line))
	{
		if ('#' == line[0])                         //第一个字符为#此行为注释
			continue;
		std::istringstream is_line(line);           //需要头文件<sstream>
		if (getline(is_line, key, '='))
		{
			if (getline(is_line, value))
				config[key] = value;
		}
	}
	file.close();
	return true;
}

PActive::PActive()
	:shmid_(0)
	,pos_(-1)
	,shm_(nullptr)
	,sem_(nullptr)
{}

PActive::~PActive()
{
	if(sem_ != nullptr)
	{
		sem_close(sem_);
	}
	//把当前进程从共享内存的进程组中移去
	if(-1 != pos_)
	{
		memset(shm_+pos_,0,sizeof(struct st_procinfo));
	}
	//把共享内存从当前进程中分离
	if(shm_!=nullptr)
		shmdt(shm_);
}
bool PActive::addProcInfo(const int timeout,const char *pname,Logger* logfile)
{
	if(-1!=pos_)
		return true;
	sem_ = sem_open("/PActive", O_CREAT, 0666, 1);
	if(SEM_FAILED == sem_)
	{
		if(logfile != nullptr)
			logfile->fatal("sem_open() failed\n");
		return false;
	}

	//创建/获取共享内存，键值为_SHMKEYP_,大小为_MAXNUMP_个st_procinfo结构体的大小
	shmid_ = shmget((key_t)_SHMKEYP_, _MAXNUMP_*sizeof(struct st_procinfo),0666|IPC_CREAT);
	if(-1 == shmid_)
	{
		if(nullptr != logfile)
			logfile->fatal("shmget() failed\n");
		return false;
	}

	//将共享内存连接到当前进程的地址空间
	shm_ = (struct st_procinfo *)shmat(shmid_,0,0);

	struct st_procinfo pinfo;    //当前进程心跳信息的结构体
	pinfo.pid = getpid();        //当前进程号
	pinfo.timeout = timeout;     //超时时间
	pinfo.atime = time(0);       //当前时间
	memset(pinfo.pname,0,51);
	strncpy(pinfo.pname,pname,50);//进程名
  // 进程id是循环使用的，如果曾经有一个进程异常退出，没有清理自己的心跳信息，它的进程信息将残留在共享内存中，不巧的是，当前进程重用了上述进程的id，这样就会在共享内存中存在两个进程id相同的记录，守护进程检查到残留进程的心跳时，会向进程id发送退出信号，这个信号将误杀当前进程.如果共享内存中存在当前进程编号，一定是其它进程残留的数据，当前进程就重用该位置。
	for(int i =0; i < _MAXNUMP_; ++i)
	{
		if ((shm_+i)->pid == pinfo.pid)
		{
			pos_ = i;
			break;
		}
	}
	//上锁
	sem_wait(sem_);
	//如果pos_==-1，共享内存的进程组中不存在当前进程编号，找一个空位置
	if (pos_==-1)
	{
		for (int i=0; i < _MAXNUMP_; ++i)
		{
			if ((shm_+i)->pid==0)
			{
				pos_ = i;
				break;
			}
		}
	}

	if (pos_ == -1)
	{
		if (logfile != nullptr)
			logfile->fatal("共享内存空间已用完\n");
		sem_post(sem_);
		return false;
	}

	//把当前进程的心跳信息存入共享内存的进程组中
	memcpy(shm_+pos_, &pinfo, sizeof pinfo);

	//解锁
	sem_post(sem_);

	return true;
}

bool PActive::uptATime()
{
	if(pos_ == -1)
		return false;
	(shm_ + pos_)->atime = time(0);
	return true;
}

